function Map (battleHandle) {
	// Special map element
	var D_CLIFF_Y_OFFSET = 18;
	var L_CLIFF_X_OFFSET = 30;
	var R_CLIFF_X_OFFSET = 30;
	var U_CLIFF_Y_OFFSET = 33;
	
	// Ground tile array. 
	// Ground[i][j] = ground tile at x = i, y = j
	this.m_ground = new Array();
	
	// Init all ground tile to snow
	for (var i=0; i<MAP_SIZE_W; i++) {
		this.m_ground[i] = new Array();
		for (var j=0; j<MAP_SIZE_H; j++) {
			this.m_ground[i][j] = MAP_TILE_SNOW;
		}
	}
	
	// Object tile array
	this.m_object = new Array();
	
	// Init all object tile to empty
	for (var i=0; i<MAP_SIZE_W; i++) {
		this.m_object[i] = new Array();
		for (var j=0; j<MAP_SIZE_H; j++) {
			this.m_object[i][j] = 0;
		}
	}
	
	// Start to load the image required
	var snowImageHandle = g_graphicEngine.LoadImage("Data/ActionPhase/Map/Ground.jpg");
	var waterImageHandle = g_graphicEngine.LoadImage("Data/ActionPhase/Map/Water.jpg");
	
	var DCliffImageHandle = g_graphicEngine.LoadImage("Data/ActionPhase/Map/DCliff.jpg");
	var LCliffImageHandle = g_graphicEngine.LoadImage("Data/ActionPhase/Map/LCliff.png");
	var RCliffImageHandle = g_graphicEngine.LoadImage("Data/ActionPhase/Map/RCliff.png");
	var UCliffImageHandle = g_graphicEngine.LoadImage("Data/ActionPhase/Map/UCliff.png");
	
	
	var bufferW = MAP_SIZE_W * MAP_TILE_SIZE;
	var bufferH = MAP_SIZE_H * MAP_TILE_SIZE;
	var bufferCanvas = document.createElement("canvas");
	var bufferContext = bufferCanvas.getContext("2d");
	bufferCanvas.width  = bufferW;
	bufferCanvas.height = bufferH;
	
	
	
	this.LoadMapFromArray = function (array, reverse) {
		for (var i=0; i<MAP_SIZE_W; i++) {
			this.m_ground[i] = new Array();
			for (var j=0; j<MAP_SIZE_H; j++) {
				if (reverse) this.m_ground[i][j] = array[j][i];
				else         this.m_ground[i][j] = array[i][j];
			}
		}
	}
	
	
	
	
	this.Update = function () {
		
	}
	
	this.Draw = function () {
		g_graphicEngine.CopyCanvas (g_context, bufferCanvas, 0, 0, bufferW, bufferH, BATTLE_OFFSET_X, BATTLE_OFFSET_Y, bufferW, bufferH);
	}
	
	
	this.Render = function () {
		g_graphicEngine.ClearCanvas (bufferContext);
		// Render all ground tile first
		for (var i=0; i<MAP_SIZE_W; i++) {
			for (var j=0; j<MAP_SIZE_H; j++) {
				if (this.m_ground[i][j] == MAP_TILE_SNOW) {
					g_graphicEngine.Draw (bufferContext, snowImageHandle, MAP_TILE_SIZE * i, MAP_TILE_SIZE * j, MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE * i, MAP_TILE_SIZE * j, MAP_TILE_SIZE, MAP_TILE_SIZE);
				}
				else if (this.m_ground[i][j] == MAP_TILE_WATER) {
					g_graphicEngine.Draw (bufferContext, waterImageHandle, 0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE * i, MAP_TILE_SIZE * j, MAP_TILE_SIZE, MAP_TILE_SIZE);
					
					if (j > 0 && this.m_ground[i][j-1] == 1) {
						g_graphicEngine.Draw (bufferContext, DCliffImageHandle, 0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE * i, MAP_TILE_SIZE * j - D_CLIFF_Y_OFFSET, MAP_TILE_SIZE, MAP_TILE_SIZE);
						g_graphicEngine.Draw (bufferContext, waterImageHandle, 0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE * i, MAP_TILE_SIZE * j, MAP_TILE_SIZE, MAP_TILE_SIZE, 0.5);
					}
					
					if (i > 0 && this.m_ground[i-1][j] == 1) {
						g_graphicEngine.Draw (bufferContext, LCliffImageHandle, 0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE * (i-1) + L_CLIFF_X_OFFSET, MAP_TILE_SIZE * j, MAP_TILE_SIZE, MAP_TILE_SIZE);
					}
					if (i < MAP_SIZE_W - 1 && this.m_ground[i+1][j] == 1) {
						g_graphicEngine.Draw (bufferContext, RCliffImageHandle, 0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE * i + L_CLIFF_X_OFFSET, MAP_TILE_SIZE * j, MAP_TILE_SIZE, MAP_TILE_SIZE);
					}
					if (j < MAP_SIZE_H - 1 && this.m_ground[i][j+1] == 1) {
						g_graphicEngine.Draw (bufferContext, UCliffImageHandle, 0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE, MAP_TILE_SIZE * i, MAP_TILE_SIZE * j + U_CLIFF_Y_OFFSET, MAP_TILE_SIZE, MAP_TILE_SIZE);
					}
				}
			}
		}
	}
}